From e09b4fa0298011eea98826edfeb966bf85228178 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 29 Apr 2013 16:25:55 +0200 Subject: [PATCH] gdkwindow: Change how paints work First of all, we now only do paints on native windows, as there is really no reason anymore to do it for subwindows. Secondly, we keep track of the paints even for GtkPaintable windows, but for that case we don't create the offscreen surface, but rather assume the windowing system does the backing store. --- gdk/gdkwindow.c | 160 ++++++++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 72 deletions(-) diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 3086bb322f..3b476e2933 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -2716,12 +2716,16 @@ gdk_window_begin_paint_region (GdkWindow *window, GdkRectangle clip_box; GdkWindowPaint *paint; GSList *list; + gboolean needs_surface; g_return_if_fail (GDK_IS_WINDOW (window)); - if (GDK_WINDOW_DESTROYED (window)) + if (GDK_WINDOW_DESTROYED (window) || + !gdk_window_has_impl (window)) return; + needs_surface = TRUE; + if (GDK_IS_PAINTABLE (window->impl)) { GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (window->impl); @@ -2729,21 +2733,23 @@ gdk_window_begin_paint_region (GdkWindow *window, if (iface->begin_paint_region) iface->begin_paint_region ((GdkPaintable*)window->impl, window, region); - return; + needs_surface = FALSE; } - paint = g_new (GdkWindowPaint, 1); + paint = g_new0 (GdkWindowPaint, 1); paint->region = cairo_region_copy (region); cairo_region_intersect (paint->region, window->clip_region); cairo_region_get_extents (paint->region, &clip_box); - paint->surface = gdk_window_create_similar_surface (window, - gdk_window_get_content (window), - MAX (clip_box.width, 1), - MAX (clip_box.height, 1)); - - cairo_surface_set_device_offset (paint->surface, -clip_box.x, -clip_box.y); + if (needs_surface) + { + paint->surface = gdk_window_create_similar_surface (window, + gdk_window_get_content (window), + MAX (clip_box.width, 1), + MAX (clip_box.height, 1)); + cairo_surface_set_device_offset (paint->surface, -clip_box.x, -clip_box.y); + } for (list = window->paint_stack; list != NULL; list = list->next) { @@ -2755,10 +2761,8 @@ gdk_window_begin_paint_region (GdkWindow *window, window->paint_stack = g_slist_prepend (window->paint_stack, paint); if (!cairo_region_is_empty (paint->region)) - { - gdk_window_clear_backing_region (window, - paint->region); - } + gdk_window_clear_backing_region (window, + paint->region); } /** @@ -2785,22 +2789,22 @@ gdk_window_end_paint (GdkWindow *window) g_return_if_fail (GDK_IS_WINDOW (window)); - if (GDK_WINDOW_DESTROYED (window)) + if (GDK_WINDOW_DESTROYED (window) || + !gdk_window_has_impl (window)) return; + if (window->paint_stack == NULL) + { + g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation"); + return; + } + if (GDK_IS_PAINTABLE (window->impl)) { GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (window->impl); if (iface->end_paint) iface->end_paint ((GdkPaintable*)window->impl); - return; - } - - if (window->paint_stack == NULL) - { - g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation"); - return; } paint = window->paint_stack->data; @@ -2808,30 +2812,35 @@ gdk_window_end_paint (GdkWindow *window) window->paint_stack = g_slist_delete_link (window->paint_stack, window->paint_stack); - cairo_region_get_extents (paint->region, &clip_box); - full_clip = cairo_region_copy (window->clip_region); - cairo_region_intersect (full_clip, paint->region); - cr = gdk_cairo_create (window); - cairo_set_source_surface (cr, paint->surface, 0, 0); - gdk_cairo_region (cr, full_clip); - cairo_clip (cr); - if (gdk_window_has_impl (window) || - window->alpha == 255) - { - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - } - else + if (paint->surface != NULL) { - cairo_set_operator (cr, CAIRO_OPERATOR_OVER); - cairo_paint_with_alpha (cr, window->alpha / 255.0); - } + cairo_region_get_extents (paint->region, &clip_box); + full_clip = cairo_region_copy (window->clip_region); + cairo_region_intersect (full_clip, paint->region); - cairo_destroy (cr); - cairo_region_destroy (full_clip); + cr = gdk_cairo_create (window); + cairo_set_source_surface (cr, paint->surface, 0, 0); + gdk_cairo_region (cr, full_clip); + cairo_clip (cr); + if (gdk_window_has_impl (window) || + window->alpha == 255) + { + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + } + else + { + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + cairo_paint_with_alpha (cr, window->alpha / 255.0); + } + + cairo_destroy (cr); + cairo_region_destroy (full_clip); + + cairo_surface_destroy (paint->surface); + } - cairo_surface_destroy (paint->surface); cairo_region_destroy (paint->region); g_free (paint); @@ -2870,7 +2879,8 @@ gdk_window_free_paint_stack (GdkWindow *window) { GdkWindowPaint *paint = tmp_list->data; - if (tmp_list == window->paint_stack) + if (tmp_list == window->paint_stack && + paint->surface != NULL) cairo_surface_destroy (paint->surface); cairo_region_destroy (paint->region); @@ -2972,14 +2982,20 @@ gdk_window_get_visible_region (GdkWindow *window) return cairo_region_copy (window->clip_region); } -static cairo_t * -setup_backing_rect (GdkWindow *window, GdkWindowPaint *paint) +static void +gdk_window_clear_backing_region (GdkWindow *window, + cairo_region_t *region) { + GdkWindowPaint *paint = window->paint_stack->data; + cairo_region_t *clip; GdkWindow *bg_window; cairo_pattern_t *pattern = NULL; int x_offset = 0, y_offset = 0; cairo_t *cr; + if (GDK_WINDOW_DESTROYED (window) || paint->surface == NULL) + return; + cr = cairo_create (paint->surface); for (bg_window = window; bg_window; bg_window = bg_window->parent) @@ -3001,22 +3017,6 @@ setup_backing_rect (GdkWindow *window, GdkWindowPaint *paint) else cairo_set_source_rgb (cr, 0, 0, 0); - return cr; -} - -static void -gdk_window_clear_backing_region (GdkWindow *window, - cairo_region_t *region) -{ - GdkWindowPaint *paint = window->paint_stack->data; - cairo_region_t *clip; - cairo_t *cr; - - if (GDK_WINDOW_DESTROYED (window)) - return; - - cr = setup_backing_rect (window, paint); - clip = cairo_region_copy (paint->region); cairo_region_intersect (clip, region); @@ -3054,7 +3054,7 @@ gdk_window_create_cairo_surface (GdkWindow *window, int height) { cairo_surface_t *surface, *subsurface; - + surface = gdk_window_ref_impl_surface (window); if (gdk_window_has_impl (window)) return surface; @@ -3073,15 +3073,21 @@ cairo_surface_t * _gdk_window_ref_cairo_surface (GdkWindow *window) { cairo_surface_t *surface; + GdkWindowPaint *paint; g_return_val_if_fail (GDK_IS_WINDOW (window), NULL); - if (window->paint_stack) - { - GdkWindowPaint *paint = window->paint_stack->data; + paint = NULL; + if (window->impl_window->paint_stack) + paint = window->impl_window->paint_stack->data; - surface = paint->surface; - cairo_surface_reference (surface); + if (paint && paint->surface != NULL) + { + surface = cairo_surface_create_for_rectangle (paint->surface, + window->abs_x, + window->abs_y, + window->width, + window->height); } else { @@ -3125,20 +3131,30 @@ _gdk_window_ref_cairo_surface (GdkWindow *window) cairo_t * gdk_cairo_create (GdkWindow *window) { + GdkWindowPaint *paint; cairo_surface_t *surface; + cairo_region_t *region; cairo_t *cr; - + g_return_val_if_fail (GDK_IS_WINDOW (window), NULL); surface = _gdk_window_ref_cairo_surface (window); cr = cairo_create (surface); - if (!window->paint_stack) + if (window->impl_window->paint_stack) { - gdk_cairo_region (cr, window->clip_region); - cairo_clip (cr); - } - + paint = window->impl_window->paint_stack->data; + + region = cairo_region_copy (paint->region); + cairo_region_translate (region, -window->abs_x, -window->abs_y); + gdk_cairo_region (cr, region); + cairo_region_destroy (region); + } + else + gdk_cairo_region (cr, window->clip_region); + + cairo_clip (cr); + cairo_surface_destroy (surface); return cr; -- 2.30.2